#include <iostream>
#include <pthread.h> //原生线程库头文件
#include <unistd.h>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <vector>

const int threadnum = 5;

class Task
{
public:
    Task(int x, int y):_x(x), _y(y)
    {}

    int Excute()
    {
        return _x + _y;
    }

    ~Task()
    {
        
    }
private:
    int _x;
    int _y;
};

class ThreadData
{
public:
    ThreadData(int x, int y, const std::string &threadname)
        :_t(x, y), _threadname(threadname)
    {}

    std::string threadname()
    {
        return _threadname;
    }

    int run()
    {
        return _t.Excute();
    }
private:
    std::string _threadname;
    Task _t;
};


class Result
{
public:
    Result(){};
    ~Result(){};

    void SetResult(int result, const std::string& threadname)
    {
        _result = result;
        _threadname = threadname;
    }

    void Print()
    {
        std::cout << _threadname << " : " << _result << std::endl;
    }
private:
    int _result;
    std:: string _threadname;//那个线程的结果
};

void* threadTask(void *args)
{
    ThreadData *td = static_cast<ThreadData *>(args);

    std::string name = td->threadname();

    Result *res = new Result;
    int result = td->run();
    res->SetResult(result, name);

    // std::cout << name << " run result : " << result << std::endl;
    delete td;

    sleep(2);
    return res;

    // // std::string threadname = static_cast<char*>(args);
    // const char* threadname = static_cast<char*>(args);

    // while (true)
    // {
    //     sleep(1);
    //     std::cout << "I am " << threadname << std::endl;
    // }

    // return nullptr;
}


// 1. 多线程创建
// 2. 线程的传参和返回值，可以传递基本信息，也可以传递对象（包括自己定义的）
int main()
{
    std::vector<pthread_t> threads;
    // std::cout << "开始运行" << std::endl;
    for (int i = 0; i < threadnum; i++)
    {
        // char threadname[64];//这里不能这样写，因为传的时threadname的地址，不要把公共的空间传递给线程
        // char* threadname = new char[64];//传递独立的堆空间

        char threadname[64];
        snprintf(threadname, 64, "Thread-%d", i + 1);
        ThreadData *td = new ThreadData(10, 20, threadname);

        pthread_t tid;
        pthread_create(&tid, nullptr, threadTask, td);
        threads.push_back(tid);
    }

    std::vector<Result*> result_set;
    void* ret = nullptr;
    for (auto &tid : threads)
    {
        pthread_join(tid, &ret);
        result_set.push_back(static_cast<Result*>(ret));
    }

    for (auto &res : result_set)
    {
        res->Print();
        delete res;
    }
    return 0;
}